package com.am.file.utils;
import com.am.file.constants.Const;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import lombok.extern.slf4j.Slf4j;

import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * MinIO工具类
 */
@Slf4j
public class MinIOUtils {

    private static MinioClient minioClient;

    private static String endpoint;
    private static String bucketName;
    private static String accessKey;
    private static String secretKey;


    public MinIOUtils() {
    }

    public MinIOUtils(String endpoint, String bucketName, String accessKey, String secretKey, Integer imgSize, Integer fileSize) {
        MinIOUtils.endpoint = endpoint;
        MinIOUtils.bucketName = bucketName;
        MinIOUtils.accessKey = accessKey;
        MinIOUtils.secretKey = secretKey;
        createMinioClient();
    }

    /**
     * 创建基于Java端的MinioClient
     */
    public void createMinioClient() {
        try {
            if (null == minioClient) {
                log.info("开始创建 MinioClient...");
                minioClient = MinioClient
                                .builder()
                                .endpoint(endpoint)
                                .credentials(accessKey, secretKey)
                                .build();
                createBucket(bucketName);
                log.info("创建完毕 MinioClient...");
            }
        } catch (Exception e) {
            log.error("MinIO服务器异常：{}", e);
        }
    }

    /**
     * 获取上传文件前缀路径
     * @return
     */


    /******************************  Operate Bucket Start  ******************************/

    /**
     * 启动SpringBoot容器的时候初始化Bucket
     * 如果没有Bucket则创建
     * @throws Exception
     */
    private static void createBucket(String bucketName) throws Exception {
        if (!bucketExists(bucketName)) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     *  判断Bucket是否存在，true：存在，false：不存在
     * @return
     * @throws Exception
     */
    public static boolean bucketExists(String bucketName) throws Exception {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    public static void createBucketIfNotExists(String bucketName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException, ServerException, InvalidKeyException {
        boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!found) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }


    public static String uploadFile(String bucketName, MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
            InputStream stream = file.getInputStream();
        System.out.println(file.getOriginalFilename());
        //上传的二进制流
            String name = UUID.randomUUID().toString();
            //随机生成文件名字
            String originalFilename = file.getOriginalFilename();
            //获得文件本来的名字
            String fileExtension = null;
            if (originalFilename != null) {
                fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                //获得文件后缀名
            }
        System.out.println("1");
            PutObjectArgs args = PutObjectArgs.builder()
                    .bucket(bucketName) // 上传桶的名字
                    .headers(Map.of(Const.CONTENT_TYPE, Objects.requireNonNull(file.getContentType())))
                    //获得文件上传的类型
                    .object(name + "." + fileExtension)
                    //获得上传文件路径从文件夹枚举字符串里获取
                    .stream(stream, file.getSize(), -1)
                    //获得上传文件内容
                    .build();
            //构造要上传的对象
            minioClient.putObject(args);
        System.out.println(fileExtension);
        //上传
            return endpoint + "/" + bucketName + "/" + name + "." + fileExtension;
        }


    public static List<String> uploadFiles(String bucketName, MultipartFile[] files) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        List<String> uploadedFileUrls = new ArrayList<>();
        for (MultipartFile file : files) {
            InputStream stream = file.getInputStream();
            System.out.println(file.getOriginalFilename());

            // 随机生成文件名字
            String name = UUID.randomUUID().toString();
            // 获得文件本来的名字
            String originalFilename = file.getOriginalFilename();

            // 获得文件后缀名
            String fileExtension = null;
            if (originalFilename != null) {
                fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            }


            // 构造要上传的对象
            PutObjectArgs args = PutObjectArgs.builder()
                    .bucket(bucketName) // 上传桶的名字
                    .headers(Map.of(Const.CONTENT_TYPE, Objects.requireNonNull(file.getContentType())))
                    .object(name + "." + fileExtension)
                    .stream(stream, file.getSize(), -1)
                    .build();
            // 上传
            minioClient.putObject(args);
            // 生成文件的访问 URL 并添加到列表中
            String fileUrl = endpoint + "/" + bucketName + "/" + name + "." + fileExtension;
            uploadedFileUrls.add(fileUrl);
        }
        return uploadedFileUrls;
    }


    public static boolean deleteFiles(List<String> fileNames) throws Exception {
        List<DeleteObject> deleteObjects = fileNames.stream().map(DeleteObject::new).collect(Collectors.toList());
        //通过文件名删除文件
        RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder()
                .bucket(bucketName)
                .objects(deleteObjects)
                .build();

        Iterable<Result<DeleteError>> results = minioClient.removeObjects(removeObjectsArgs);
        //调用删除函数
        for (Result<DeleteError> result : results) {
            DeleteError error = result.get();
            log.error("文件: " + error.objectName() + "删除错误; ", error.message());
            return false;
        }
        return true;
    }

    public static void main(String[] args) throws Exception {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("40085e1a-cb90-4bb6-b198-12e27e0b9adf.png");
        boolean b = deleteFiles(strings);
        System.out.println(b);
    }
}

